#-*- coding: utf-8 -*-
'''
Created on Oct 27, 2012

@author: bbg
'''

from service.public.service_base import ServiceBase
from common.debug import Debug
from protocol.unpay_order_pb2 import UploadOrderRequest
from dbwrapper.shopx.order_main import OrderMain
from dbwrapper.shopx.order_dishes import OrderDishes
from dbwrapper.shopx.order_subdishes import OrderSubdishes
from dbwrapper.shopx.order_payment_mode import OrderPaymentMode
import datetime
import json

class OrderService(ServiceBase):
    '''
        处理订单上传操作
    '''
    def __init__(self, start_response):
        ServiceBase.__init__(self, start_response)
        self.debug = Debug()
    
    def application(self, params):      

        order_bin_data = params.getvalue('binary')        
       
        if order_bin_data == None:
            self.debug.e('OrderService, no binary data')
            return self._responseInvalidParam()
        
        order_request = UploadOrderRequest()
        try:
            order_request.ParseFromString(order_bin_data)
        except Exception,e:
            self.debug.e('OrderService,parse from upload order data failed:%s' % e)
            return self._responseInvalidParam()
                
        #translate to dict， check login status
        dictParams = {}
        dictParams['cdkey'] = order_request.cdkey
        dictParams['uuid'] = order_request.uuid
        dictParams['username'] = order_request.username
        dictParams['token'] = order_request.token
        if self._isClientLogin(dictParams) == False:
            (company_id, shop_id) = self._getCompanyShopId()
            if company_id == None or shop_id == None:
                return self._responseError(106, "company_id或shop_id未获取到，可能是cdkey有错")
            else:           
                return self._responseError(107, "无效登陆token")
        
        try:
            dbsession = self._returndbsession()
            (company_id, shop_id) = self._getCompanyShopId()
            
            #map database            
            cur_year = datetime.datetime.now().strftime("%Y")
            OrderMain.doMapping(company_id, shop_id, cur_year)
            OrderDishes.doMapping(company_id, shop_id, cur_year)
            OrderSubdishes.doMapping(company_id, shop_id, cur_year)
            OrderPaymentMode.doMapping(company_id, shop_id, cur_year)
            self.debug.d("order_service:application, company id:%s, shop id:%s, cur_year:%s" % (company_id, shop_id, cur_year))
                        
            orderid = order_request.orderid
            rows = dbsession.query(OrderMain).filter(OrderMain.order_id == orderid)
            
                        
            self._saved_autocommit = dbsession.autocommit
            self._saved_autoflush = dbsession.autoflush
            dbsession.autocommit = False
            dbsession.autoflush = False
            
            if rows.count() == 0:
                #insert a new order
                self.insertOrder(order_request, dbsession)
            else:
                #replace order
                self.replaceOrder(order_request, dbsession)        
                                            
            dbsession.autocommit = self._saved_autocommit
            dbsession.autoflush = self._saved_autoflush
            
            self.debug.d("order_service:application sync order %s success" % orderid)
            response_params={}
            response_params['ret'] = 0
            response_params['msg'] = "order %s sync ok" % orderid
            return self._response(json.dumps(response_params))
        except Exception as e:
            self.debug.e('order_service:application order %s sync failed:%s' % (orderid, e))
            dbsession.rollback()
            return self._responseError(-1, 'order %s sync failed' % orderid)
        except:
            self.debug.e('order_service:application order %s sync failed: unknown exception, raise' % orderid)
            dbsession.rollback()
            raise
    
    def insertOrder(self, order_request, dbsession):        
        #dbsession.begin() 
        #note: the 'dbsession' has automatically start a transition       
        
        self._prepareInsert(order_request, dbsession)
                        
        if dbsession.flush() == False:
            dbsession.rollback()
            return False
        if dbsession.commit() == False:
            dbsession.rollback()
            return False
        
        return True        
        
    def replaceOrder(self, order_request, dbsession):
        orderid = order_request.orderid
        
        #dbsession.begin()
        
        dbsession.query(OrderMain).filter(OrderMain.order_id == orderid).delete()
        dbsession.query(OrderDishes).filter(OrderDishes.order_id == orderid).delete()
        dbsession.query(OrderSubdishes).filter(OrderSubdishes.order_id == orderid).delete()
        dbsession.query(OrderPaymentMode).filter(OrderPaymentMode.order_id == orderid).delete()
        
        self._prepareInsert(order_request, dbsession)
        
        if dbsession.flush() == False:
            dbsession.rollback()
            return False
        if dbsession.commit() == False:
            dbsession.rollback()
            return False
        
        return True
    
    def _prepareInsert(self, order_request, dbsession):
        orderid = order_request.orderid        
        order_main_input = order_request.order_table_new
        order_dishes_input = order_request.order_table_dishs
        order_subdishes_input = order_request.order_table_subdishs
        order_pay_input = order_request.order_table_pay
                
        nowTime = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        
        #order_main table
        order_main = OrderMain()
        order_main.order_id = orderid
        order_main.room_alias_id = order_main_input.room_alias_id
        order_main.room_mark = order_main_input.room_mark
        order_main.person_count = order_main_input.people_count
        order_main.amount = order_main_input.amount
        order_main.room_state = order_main_input.room_state
        order_main.open_time = order_main_input.open_time
        order_main.close_time = order_main_input.close_time
        order_main.final_amount = order_main_input.final_amount
        order_main.discount_rate = order_main_input.discount_rate
        order_main.discount_amount = order_main_input.discount_amount
        order_main.free_amount = order_main_input.free_amount
        order_main.service_fee_rate = order_main_input.service_fee_rate
        order_main.service_amount = order_main_input.service_amount
        order_main.opener = order_main_input.openuser
        order_main.casher = order_main_input.cashuser
        order_main.extra_amount = order_main_input.extra_amount
        order_main.create_time = nowTime
        order_main.modify_time = nowTime
        
        #TODO:
        dbsession.add(order_main)
        self.debug.d("OrderService:_prepareInsert, order_main add, orderid %s" % orderid)
                
        insertTime = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        
        #order_dishes table
        for dishes in order_dishes_input:
            order_dishes = OrderDishes()
            order_dishes.order_id = orderid
            order_dishes.inner_rank_id = dishes.inner_rank_id
            order_dishes.dish_id = dishes.dish_id
            order_dishes.dish_name = dishes.dish_name
            order_dishes.dish_count = dishes.dish_count
            order_dishes.dish_price = dishes.dish_price
            order_dishes.dish_unit = dishes.dish_unit
            order_dishes.unit_inner_rank_id = dishes.unit_inner_rank_id
            order_dishes.order_time = insertTime
            order_dishes.is_free = dishes.is_free
            order_dishes.is_cook = dishes.is_cook
            order_dishes.order_mode = dishes.order_mode
            order_dishes.order_man = dishes.order_man
            order_dishes.operator = dishes.operator
            order_dishes.discount_rate = dishes.discount_rate
            order_dishes.is_service_charge = dishes.is_service_charge
            order_dishes.cook_content = dishes.cook_content
            order_dishes.cook_extra_charge = dishes.cook_extra_charge
            order_dishes.original_price = dishes.original_price
            order_dishes.stat_class_name = dishes.stat_class
            order_dishes.printer_name = dishes.printer_name
            order_dishes.create_time = nowTime
            order_dishes.modify_time = nowTime            
             
            #TODO:   
            dbsession.add(order_dishes)
        self.debug.d("OrderService:_prepareInsert, order_dishes added %d recored" % len(order_dishes_input))
        
        #order_subdishes table
        for subdishes in order_subdishes_input:
            order_subdishes = OrderSubdishes()
            
            order_subdishes.order_id = orderid
            order_subdishes.inner_rank_id = subdishes.dish_id
           
            order_subdishes.dish_id = subdishes.dish_id
            order_subdishes.dish_name = subdishes.dish_name
            order_subdishes.dish_count = subdishes.dish_count
            order_subdishes.dish_price = subdishes.dish_price
            order_subdishes.dish_unit = subdishes.dish_unit
            order_subdishes.unit_inner_rank_id = subdishes.unit_inner_rank_id
            order_subdishes.order_time = insertTime
            order_subdishes.is_cook = subdishes.is_cook
            order_subdishes.order_mode = subdishes.order_mode
            order_subdishes.order_man = subdishes.order_man
            order_subdishes.operator = subdishes.operator
            order_subdishes.discount_rate = subdishes.discount_rate
            order_subdishes.is_service_charge = subdishes.is_service_charge
            order_subdishes.cook_content = subdishes.cook_content
            order_subdishes.cook_extra_charge = subdishes.cook_extra_charge
            order_subdishes.original_price = subdishes.original_price
            order_subdishes.stat_class_name = subdishes.stat_class_name
            order_subdishes.printer_name = subdishes.printer_name               
            order_subdishes.sub_inner_rank_id = subdishes.sub_inner_rank_id
            order_subdishes.create_time = nowTime
            order_subdishes.modify_time = nowTime   
                  
            #TODO:
            dbsession.add(order_subdishes)
            
        self.debug.d("OrderService:_prepareInsert, order_subdishes added %d recoreds" % len(order_subdishes_input))

        
        #order_pay table
        for pay in order_pay_input:
            order_pay = OrderPaymentMode()
            
            order_pay.order_id = orderid
            order_pay.payment_name = pay.payment_name
            order_pay.amount = pay.amount
            order_pay.exchange_rate = pay.exchange_rate
            order_pay.original_cash_amount = pay.original_cash_amount
            order_pay.create_time = nowTime
            order_pay.modify_time = nowTime
            
            dbsession.add(order_pay)
            #TODO:       
            self.debug.d("OrderService:_prepareInsert, order_pay add")

    
